/*********************************************************************************
  *Copyright(C),2015-2020, 涂鸦科技 www.tuya.comm
  *FileName: tuya_ipc_system_control_demo.c
  *
  * 文件描述：
  * 该demo显示了涂鸦SDK如何使用callback的方式实现系统控制如：
  * 1. 设置本地ID。
  * 2. 重启System和重启进程。
  * 3. OTA升级。
  * 4. 声音和LED提示。
  *
**********************************************************************************/

#include <string.h>
#include <stdio.h>
#include "tuya_ipc_media.h"
#include "tuya_cloud_com_defs.h"
#include "tuya_cloud_types.h"
#include "tuya_ipc_common_demo.h"
#include "tuya_ipc_system_control_demo.h"

extern IPC_MGR_INFO_S s_mgr_info;

/* 
当用户在APP上点击移除设备时的回调
*/
VOID IPC_APP_Reset_System_CB(GW_RESET_TYPE_E type)
{
    printf("reset ipc success. please restart the ipc %d\n", type);
    IPC_APP_Notify_LED_Sound_Status_CB(IPC_RESET_SUCCESS);
    //TODO
    /* 开发者需要实现重启IPC的操作 */
}

VOID IPC_APP_Restart_Process_CB(VOID)
{
    printf("sdk internal restart request. please restart the ipc\n");
    //TODO
    /* 开发者需要实现重启的操作。重启进程或者重启整个设备。 */
}

/* OTA 相关 */
//OTA文件下载完成后的回调
VOID __IPC_APP_upgrade_notify_cb(IN CONST FW_UG_S *fw, IN CONST INT_T download_result, IN PVOID_T pri_data)
{
    FILE *p_upgrade_fd = (FILE *)pri_data;
    fclose(p_upgrade_fd);

    PR_DEBUG("Upgrade Finish");
    PR_DEBUG("download_result:%d fw_url:%s", download_result, fw->fw_url);

    if(download_result == 0)
    {
        /* 开发者需要实现OTA升级的操作，此时OTA文件已经下载成功到指定的路径。 [ p_mgr_info->upgrade_file_path ]。 */
    }
    //TODO
    //reboot system
}

//分片收取OTA文件，追加写到本地文件中
OPERATE_RET __IPC_APP_get_file_data_cb(IN CONST FW_UG_S *fw, IN CONST UINT_T total_len,IN CONST UINT_T offset,
                             IN CONST BYTE_T *data,IN CONST UINT_T len,OUT UINT_T *remain_len, IN PVOID_T pri_data)
{
    PR_DEBUG("Rev File Data");
    PR_DEBUG("total_len:%d  fw_url:%s", total_len, fw->fw_url);
    PR_DEBUG("Offset:%d Len:%d", offset, len);

    FILE *p_upgrade_fd = (FILE *)pri_data;
    fwrite(data, 1, len, p_upgrade_fd);
    *remain_len = 0;

    return OPRT_OK;
}

VOID IPC_APP_Upgrade_Inform_cb(IN CONST FW_UG_S *fw)
{
    PR_DEBUG("Rev Upgrade Info");
    PR_DEBUG("fw->fw_url:%s", fw->fw_url);
    PR_DEBUG("fw->fw_md5:%s", fw->fw_md5);
    PR_DEBUG("fw->sw_ver:%s", fw->sw_ver);
    PR_DEBUG("fw->file_size:%u", fw->file_size);

    FILE *p_upgrade_fd = fopen(s_mgr_info.upgrade_file_path, "w+b");
    tuya_ipc_upgrade_sdk(fw, __IPC_APP_get_file_data_cb, __IPC_APP_upgrade_notify_cb, p_upgrade_fd);
}

/* 需要开发者实现对应的提示音播放和LED提示，可以参考SDK附带的文件，使用TUYA音频文件 */
VOID IPC_APP_Notify_LED_Sound_Status_CB(IPC_APP_NOTIFY_EVENT_E notify_event)
{
    printf("curr event:%d \r\n", notify_event);
    switch (notify_event)
    {
        case IPC_BOOTUP_FINISH: /* 启动成功 */
        {
            break;
        }
        case IPC_START_WIFI_CFG: /* 开始配置网络 */
        {
            break;
        }
        case IPC_REV_WIFI_CFG: /* 收到网络配置信息 */
        {
            break;
        }
        case IPC_CONNECTING_WIFI: /* 开始连接WIFI */
        {
            break;
        }
        case IPC_MQTT_ONLINE: /* MQTT上线 */
        {
            break;
        }
        case IPC_RESET_SUCCESS: /* 重置完成 */
        {
            break;
        }
        default:
        {
            break;
        }
    }
}

/* 对讲模式声音回调，开启关闭扬声器硬件 */
VOID TUYA_APP_Enable_Speaker_CB(BOOL_T enabled)
{
    printf("enable speaker %d \r\n", enabled);
    //TODO
    /* 开发者需要实现开启关闭扬声器硬件操作，如果IPC硬件特性无需显式开启，该函数留空即可 */
}

/* 对讲模式声音回调，开启关闭扬声器硬件 */
VOID TUYA_APP_Rev_Audio_CB(IN CONST MEDIA_FRAME_S *p_audio_frame,
                           TUYA_AUDIO_SAMPLE_E audio_sample,
                           TUYA_AUDIO_DATABITS_E audio_databits,
                           TUYA_AUDIO_CHANNEL_E audio_channel)
{
    printf("rev audio cb len:%u sample:%d db:%d channel:%d\r\n", p_audio_frame->size, audio_sample, audio_databits, audio_channel);
    //PCM-Format 8K 16Bit MONO
    //TODO
    /* 开发者需要实现扬声器播放声音操作 */

}

OPERATE_RET IPC_APP_Sync_Utc_Time(VOID)
{
    TIME_T time_utc;
    INT_T time_zone;
    OPERATE_RET ret = tuya_ipc_get_service_time(&time_utc, &time_zone);

    if(ret != OPRT_OK)
    {
        return ret;
    }
    //API返回OK，说明成功获取到了UTC时间，如果返回不是OK，说明还没有取到时间。

    PR_DEBUG("Get Server Time Success: %lu %d", time_utc, time_zone);
//  TODO
//  使用对应的系统接口设置时间如 settimeofday;

    return OPRT_OK;
}


